Jobs now send back their own description when they start
authorPierre Krieger <pierre.krieger1708@gmail.com>
Mon, 27 Oct 2014 16:09:21 +0000 (17:09 +0100)
committerAlex Crichton <alex@alexcrichton.com>
Wed, 5 Nov 2014 19:37:34 +0000 (11:37 -0800)
src/cargo/ops/cargo_rustc/fingerprint.rs
src/cargo/ops/cargo_rustc/job.rs
src/cargo/ops/cargo_rustc/job_queue.rs
src/cargo/ops/cargo_rustc/mod.rs

index 135cffeee96a9a19e75a434d4a2cfdba6a4b3bfa..d13381dc5b5c92dda63c6f9be932ed03834061de 100644 (file)
@@ -143,7 +143,7 @@ pub fn prepare_build_cmd(cx: &mut Context, pkg: &Package)
     let kind = KindTarget;
 
     if pkg.get_manifest().get_build().len() == 0 {
-        return Ok((Fresh, proc() Ok(()), proc() Ok(())))
+        return Ok((Fresh, proc(_) Ok(()), proc(_) Ok(())))
     }
     let (old, new) = dirs(cx, pkg, kind);
     let old_loc = old.join("build");
@@ -171,8 +171,8 @@ pub fn prepare_init(cx: &mut Context, pkg: &Package, kind: Kind)
     let (_, new1) = dirs(cx, pkg, kind);
     let new2 = new1.clone();
 
-    let work1 = proc() { try!(fs::mkdir(&new1, USER_RWX)); Ok(()) };
-    let work2 = proc() { try!(fs::mkdir(&new2, USER_RWX)); Ok(()) };
+    let work1 = proc(_) { try!(fs::mkdir(&new1, USER_RWX)); Ok(()) };
+    let work2 = proc(_) { try!(fs::mkdir(&new2, USER_RWX)); Ok(()) };
 
     (work1, work2)
 }
@@ -181,12 +181,14 @@ pub fn prepare_init(cx: &mut Context, pkg: &Package, kind: Kind)
 /// instances to actually perform the necessary work.
 fn prepare(is_fresh: bool, loc: Path, fingerprint: String,
            to_copy: Vec<(Path, Path)>) -> Preparation {
-    let write_fingerprint = proc() {
+    let write_fingerprint = proc(desc_tx) {
+        drop(desc_tx);
         try!(File::create(&loc).write_str(fingerprint.as_slice()));
         Ok(())
     };
 
-    let move_old = proc() {
+    let move_old = proc(desc_tx) {
+        drop(desc_tx);
         for &(ref src, ref dst) in to_copy.iter() {
             try!(fs::rename(src, dst));
         }
index 34853a26e546b5bc0748a3c1d784cdd8c327d9bd..fbf269a389b76737b56f79cdc97e742a4e9d4d14 100644 (file)
@@ -1,18 +1,16 @@
-use std::io::IoResult;
-
-use core::MultiShell;
 use util::{CargoResult, Fresh, Dirty, Freshness};
 
-pub struct Job { dirty: Work, fresh: Work, desc: String }
+pub struct Job { dirty: Work, fresh: Work }
 
-pub type Work = proc():Send -> CargoResult<()>;
+/// Each proc should send its description before starting.
+/// It should send either once or close immediatly.
+pub type Work = proc(Sender<String>):Send -> CargoResult<()>;
 
 impl Job {
     /// Create a new job representing a unit of work.
-    pub fn new(dirty: proc():Send -> CargoResult<()>,
-               fresh: proc():Send -> CargoResult<()>,
-               desc: String) -> Job {
-        Job { dirty: dirty, fresh: fresh, desc: desc }
+    pub fn new(dirty: Work,
+               fresh: Work) -> Job {
+        Job { dirty: dirty, fresh: fresh }
     }
 
     /// Create a new job which will run `fresh` if the job is fresh and
@@ -20,25 +18,17 @@ impl Job {
     ///
     /// Retains the same signature as `new` for compatibility. This job does not
     /// describe itself to the console.
-    pub fn noop(_dirty: proc():Send -> CargoResult<()>,
-                fresh: proc():Send -> CargoResult<()>,
-                _desc: String) -> Job {
-        Job { dirty: proc() Ok(()), fresh: fresh, desc: String::new() }
+    pub fn noop(_dirty: Work,
+                fresh: Work) -> Job {
+        Job { dirty: proc(_) Ok(()), fresh: fresh }
     }
 
     /// Consumes this job by running it, returning the result of the
     /// computation.
-    pub fn run(self, fresh: Freshness) -> CargoResult<()> {
+    pub fn run(self, fresh: Freshness, sender: Sender<String>) -> CargoResult<()> {
         match fresh {
-            Fresh => (self.fresh)(),
-            Dirty => (self.dirty)(),
-        }
-    }
-
-    pub fn describe(&self, shell: &mut MultiShell) -> IoResult<()> {
-        if self.desc.len() > 0 {
-            try!(shell.status("Running", self.desc.as_slice()));
+            Fresh => (self.fresh)(sender),
+            Dirty => (self.dirty)(sender),
         }
-        Ok(())
     }
 }
index 5097267d91c49c0c07fd5c20f1d1777d3865b7fd..1a54a9b3bb69060e88998cf92d73be9c953e6fde 100644 (file)
@@ -182,12 +182,21 @@ impl<'a, 'b> JobQueue<'a, 'b> {
             let fresh = job_freshness.combine(fresh);
             let my_tx = self.tx.clone();
             let id = id.clone();
-            if fresh == Dirty {
-                try!(config.shell().verbose(|shell| job.describe(shell)));
-            }
+            let (desc_tx, desc_rx) = channel();
             self.pool.execute(proc() {
-                my_tx.send((id, stage, fresh, job.run(fresh)));
+                my_tx.send((id, stage, fresh, job.run(fresh, desc_tx)));
             });
+            if fresh == Dirty {
+                // TODO: only the first message of each job is processed
+                match desc_rx.recv_opt() {
+                    Ok(ref msg) if msg.len() >= 1 => {
+                        try!(config.shell().verbose(|shell| {
+                            shell.status("Running", msg.as_slice())
+                        }));
+                    },
+                    _ => ()
+                }
+            }
         }
 
         // If no work was scheduled, make sure that a message is actually send
index 842654207f6d8b8f67032074f349f503cb896d21..b0b0d4e4e01d3b8b51162394e3e04a6dcd8c18fd 100644 (file)
@@ -147,10 +147,10 @@ fn compile<'a, 'b>(targets: &[&'a Target], pkg: &'a Package,
 
     // Prepare the fingerprint directory as the first step of building a package
     let (target1, target2) = fingerprint::prepare_init(cx, pkg, KindTarget);
-    let mut init = vec![(Job::new(target1, target2, String::new()), Fresh)];
+    let mut init = vec![(Job::new(target1, target2), Fresh)];
     if cx.config.target().is_some() {
         let (plugin1, plugin2) = fingerprint::prepare_init(cx, pkg, KindForHost);
-        init.push((Job::new(plugin1, plugin2, String::new()), Fresh));
+        init.push((Job::new(plugin1, plugin2), Fresh));
     }
     jobs.enqueue(pkg, jq::StageStart, init);
 
@@ -163,14 +163,14 @@ fn compile<'a, 'b>(targets: &[&'a Target], pkg: &'a Package,
                                                        Vec::new(), Vec::new());
     for &target in targets.iter() {
         let work = if target.get_profile().is_doc() {
-            let (rustdoc, desc) = try!(rustdoc(pkg, target, cx));
-            vec![(rustdoc, KindTarget, desc)]
+            let rustdoc = try!(rustdoc(pkg, target, cx));
+            vec![(rustdoc, KindTarget)]
         } else {
             let req = cx.get_requirement(pkg, target);
             let mut rustc = try!(rustc(pkg, target, cx, req));
 
             if target.get_profile().is_custom_build() {
-                for &(ref mut work, _, _) in rustc.iter_mut() {
+                for &(ref mut work, _) in rustc.iter_mut() {
                     use std::mem;
 
                     let (old_build, script_output) = {
@@ -200,11 +200,11 @@ fn compile<'a, 'b>(targets: &[&'a Target], pkg: &'a Package,
                     // 1 - create the output directory
                     // 2 - call rustc
                     // 3 - execute the command
-                    let rustc_cmd = mem::replace(work, proc() Ok(()));
-                    let replacement = proc() {
+                    let rustc_cmd = mem::replace(work, proc(_) Ok(()));
+                    let replacement = proc(desc_tx: Sender<String>) {
                         try!(create_directory());
-                        try!(rustc_cmd());
-                        execute_cmd()
+                        try!(rustc_cmd(desc_tx.clone()));
+                        execute_cmd(desc_tx)
                     };
                     mem::replace(work, replacement);
                 }
@@ -222,12 +222,15 @@ fn compile<'a, 'b>(targets: &[&'a Target], pkg: &'a Package,
             (false, false, _) if target.get_profile().get_env() == "test" => &mut tests,
             (false, false, _) => &mut bins,
         };
-        for (work, kind, desc) in work.into_iter() {
+        for (work, kind) in work.into_iter() {
             let (freshness, dirty, fresh) =
                 try!(fingerprint::prepare_target(cx, pkg, target, kind));
 
-            let dirty = proc() { try!(work()); dirty() };
-            dst.push((job(dirty, fresh, desc), freshness));
+            let dirty = proc(desc_tx: Sender<String>) {
+                try!(work(desc_tx.clone()));
+                dirty(desc_tx)
+            };
+            dst.push((job(dirty, fresh), freshness));
         }
     }
 
@@ -250,11 +253,12 @@ fn compile<'a, 'b>(targets: &[&'a Target], pkg: &'a Package,
             1 => pkg.get_manifest().get_build()[0].to_string(),
             _ => format!("custom build commands"),
         };
-        let dirty = proc() {
-            for cmd in build_cmds.into_iter() { try!(cmd()) }
-            dirty()
+        let dirty = proc(desc_tx: Sender<String>) {
+            desc_tx.send_opt(desc).ok();
+            for cmd in build_cmds.into_iter() { try!(cmd(desc_tx.clone())) }
+            dirty(desc_tx)
         };
-        jobs.enqueue(pkg, jq::StageCustomBuild, vec![(job(dirty, fresh, desc),
+        jobs.enqueue(pkg, jq::StageCustomBuild, vec![(job(dirty, fresh),
                                                       freshness)]);
     }
 
@@ -319,7 +323,8 @@ fn compile_custom_old(pkg: &Package, cmd: &str,
     }
     let pkg = pkg.to_string();
 
-    Ok(proc() {
+    Ok(proc(desc_tx: Sender<String>) {
+        desc_tx.send_opt(p.to_string()).ok();
         if first {
             try!(if old_output.exists() {
                 fs::rename(&old_output, &output)
@@ -470,7 +475,9 @@ fn prepare_execute_custom_build(pkg: &Package, root_pkg: &Package, target: &Targ
 
     // Building command
     let pkg = pkg.to_string();
-    let work = proc() {
+    let work = proc(desc_tx: Sender<String>) {
+        desc_tx.send_opt(build_output.display().to_string()).ok();
+
         if !build_output.exists() {
             try!(fs::mkdir(&build_output, USER_RWX)
                 .chain_error(|| {
@@ -502,13 +509,12 @@ fn prepare_execute_custom_build(pkg: &Package, root_pkg: &Package, target: &Targ
 
 fn rustc(package: &Package, target: &Target,
          cx: &mut Context, req: PlatformRequirement)
-         -> CargoResult<Vec<(Work, Kind, String)> >{
+         -> CargoResult<Vec<(Work, Kind)> >{
     let crate_types = target.rustc_crate_types();
     let rustcs = try!(prepare_rustc(package, target, crate_types, cx, req));
 
     Ok(rustcs.into_iter().map(|(rustc, kind)| {
         let name = package.get_name().to_string();
-        let desc = rustc.to_string();
         let is_path_source = package.get_package_id().get_source_id().is_path();
         let show_warnings = package.get_package_id() == cx.resolve.root() ||
                             is_path_source;
@@ -524,7 +530,7 @@ fn rustc(package: &Package, target: &Target,
             build_cmd_layout.build(pkg).join("output")
         }).collect::<Vec<_>>();
 
-        (proc() {
+        (proc(desc_tx: Sender<String>) {
             let mut rustc = rustc;
 
             let mut additional_library_paths = Vec::new();
@@ -561,13 +567,14 @@ fn rustc(package: &Package, target: &Target,
                 rustc = rustc.arg("-l").arg(lib);
             }
 
+            desc_tx.send_opt(rustc.to_string()).ok();
             try!(rustc.exec().chain_error(|| {
                 human(format!("Could not compile `{}`.", name))
             }));
 
             Ok(())
 
-        }, kind, desc)
+        }, kind)
     }).collect())
 }
 
@@ -596,7 +603,7 @@ fn prepare_rustc(package: &Package, target: &Target, crate_types: Vec<&str>,
 
 
 fn rustdoc(package: &Package, target: &Target,
-           cx: &mut Context) -> CargoResult<(Work, String)> {
+           cx: &mut Context) -> CargoResult<Work> {
     let kind = KindTarget;
     let pkg_root = package.get_root();
     let cx_root = cx.layout(package, kind).proxy().dest().join("doc");
@@ -621,7 +628,8 @@ fn rustdoc(package: &Package, target: &Target,
     let primary = package.get_package_id() == cx.resolve.root();
     let name = package.get_name().to_string();
     let desc = rustdoc.to_string();
-    Ok((proc() {
+    Ok(proc(desc_tx: Sender<String>) {
+        desc_tx.send(desc);
         if primary {
             try!(rustdoc.exec().chain_error(|| {
                 human(format!("Could not document `{}`.", name))
@@ -640,7 +648,7 @@ fn rustdoc(package: &Package, target: &Target,
             }))
         }
         Ok(())
-    }, desc))
+    })
 }
 
 fn build_base_args(cx: &Context,